package cz.muni.fi.pb138.videoweb2013.backend;

import java.io.BufferedInputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.odftoolkit.simple.SpreadsheetDocument;
import org.odftoolkit.simple.table.Table;

/**
 * Class providing import from ODF Spreadsheet file and export into it.
 * 
 * @author Martin Kubicek
 * @version 1.5
 * @since 2013-05-14
 */
public class ODFTransformationImpl implements ODFTransformation{

    //sirka znaku v milimetrech v bunkach
    private static final double WIDTH=2.4;
    private static final MediumManager manager = new MediumManagerImpl();
   
    @Override
    public void exportAll(OutputStream outputStream) {
        SpreadsheetDocument output;

        try {
            output = SpreadsheetDocument.newSpreadsheetDocument();
            java.util.List<Medium> all = manager.getAll();
            
            //pro prazdnou databazi
            if(all!=null) {
                Iterator<Medium> iterAll = all.iterator();
                int line = 0;
                Table table = null;
                //projiti iteratorem celou kolekci... vsechny zaznamy/radky
                while(iterAll.hasNext()) {
                    Medium medium = iterAll.next();
                    //mapa jednoho radku
                    java.util.Map<String, String> mapLine = medium.getItem();
                    //list hlavicky;
                    java.util.List<String> listHeader = medium.getHeader();

                    //pokud neexistuje kategorie, vytvori se a udela se hlavicka
                    if(output.getSheetByName(medium.getCathegoryName())==null) {
                        line=0;
                        output.appendSheet(medium.getCathegoryName());
                        table = output.getSheetByName(medium.getCathegoryName());

                        //vytvorime hlavicku
                        Iterator<String> iterHeader = listHeader.iterator();
                        int column=0;
                        while(iterHeader.hasNext()) {
                            String value = iterHeader.next();
                            table.getCellByPosition(column, line).setStringValue(value);
                            table.getColumnByIndex(column).setWidth(value.length()*WIDTH);

                            column++;
                        }
                        line++;
                    }

                    //pridat radky do ods
                    for(int column=0;column < listHeader.size();column++) {
                        String value = mapLine.get(listHeader.get(column));
                        
                        if(table==null) throw new NullPointerException("Table is null.. This can never happen.");

                        if(table.getColumnByIndex(column).getWidth()<value.length()*WIDTH) {
                            table.getColumnByIndex(column).setWidth(value.length()*WIDTH);
                        }
                        output.getSheetByName(medium.getCathegoryName()).getCellByPosition(column, line).setStringValue(value);
                    }
                    line++;
                }

                output.removeSheet(0);
            }
            output.save(outputStream);
            Logger.getLogger(ODFTransformationImpl.class.getName()).log(Level.INFO, "Export into file has been finished.");
        } catch (NullPointerException ex) {
            Logger.getLogger(ODFTransformationImpl.class.getName()).log(Level.SEVERE, "ERROR: null should not be here.", ex);
        } catch (Exception ex) {
            Logger.getLogger(ODFTransformationImpl.class.getName()).log(Level.SEVERE, "ERROR: unable to save output file.", ex);
        }
    }

    @Override
    public void importODF(BufferedInputStream bInputStream) {
        SpreadsheetDocument input;
        
        try {
            input = SpreadsheetDocument.loadDocument(bInputStream);

            java.util.List<Table> tableList = new java.util.ArrayList<Table>();

            for (int sheetNum = 0; sheetNum < input.getSheetCount(); sheetNum++) {
                Boolean isEmpty = true;

                //zjisti, zda je listHeader prazdny(tj. ma prazdnou hlavicku)
                for (int j = 0; j < input.getSheetByIndex(sheetNum).getColumnCount(); j++) {   
                    if (!input.getSheetByIndex(sheetNum).getRowByIndex(0).getCellByIndex(j).getDisplayText().equals("")) {
                        isEmpty = false;
                        break;
                    }
                }
                //do listu listy, ktere neco maji
                if (!isEmpty) {
                    tableList.add(input.getSheetByIndex(sheetNum));    
                }
            }
            
            java.util.List<Integer> realColumnCountList = new java.util.ArrayList<Integer>();
            //pocet sloupcu, ktere budou vybirany
            for (int tableNum = 0; tableNum < tableList.size(); tableNum++) {        
                int realColumnCount = 0;
                for (int column = 0; column < tableList.get(tableNum).getColumnCount(); column++) {
                    if(tableList.get(tableNum).getColumnByIndex(column).getCellByIndex(0).getDisplayText().equals("") &&
                        tableList.get(tableNum).getColumnByIndex(column+1).getCellByIndex(0).getDisplayText().equals("") &&
                        tableList.get(tableNum).getColumnByIndex(column+2).getCellByIndex(0).getDisplayText().equals("")) {
                        break;
                    } else {
                        realColumnCount++;
                    }
                }
                realColumnCountList.add(realColumnCount);
            }
            
            //pridavani do managera
            for (int tableNum = 0; tableNum < tableList.size(); tableNum++) {
                String category = tableList.get(tableNum).getTableName();
                
                int row=1;
                while(true) {
                    java.util.Map<String, String> line = new java.util.TreeMap<String, String>();
                    java.util.List<String> header = new java.util.ArrayList<String>();
                    boolean notEmpty = false;
                    for (int cellInRow = 0; cellInRow < realColumnCountList.get(tableNum); cellInRow++) {
                        String columnName = input.getSheetByIndex(tableNum).getRowByIndex(0).getCellByIndex(cellInRow).getDisplayText();
                        String value = input.getSheetByIndex(tableNum).getRowByIndex(row).getCellByIndex(cellInRow).getDisplayText();
                        
                        if(!value.equals("")) {
                            notEmpty = true;
                        }
                        //vsechny bunky v radku
                        line.put(columnName, value);   
                        header.add(columnName);
                    }
                    if(notEmpty) {
                        manager.addRecord(new Medium(line, category, category.replaceAll("\\s", ""), header));
                    }
                    else break;
                    row++;
                }
            }
            Logger.getLogger(ODFTransformationImpl.class.getName()).log(Level.INFO, "Import from file has been finished.");
        } catch (Exception ex) {
            Logger.getLogger(ODFTransformationImpl.class.getName()).log(Level.SEVERE, "ERROR: unable to open input file.", ex);
        }
    }
    
}
